package lol.clann.bukkit.pluginboot.command;

import org.bukkit.command.CommandSender;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;


public class SubCommand {

    public final CommandAnnotation annotation;
    public final Method method;
    public final Parameter[] parameters;
    public String desc;

    public SubCommand(CommandAnnotation annotation, Method method) {
        parameters = method.getParameters();
        this.annotation = annotation;
        this.method = method;
        this.desc = annotation.des();
        validate();
    }

    /**
     * 校验参数列表合法性
     */
    private void validate() {
        for (Parameter parameter : parameters) {
            if (parameter.getAnnotation(Sender.class) != null) {
                if (CommandSender.class.isAssignableFrom(parameter.getType())) {
                    continue;
                }
                throw new IllegalArgumentException("@Sender注解只能注解与CommandSender子类上," + method.toString());
            }
            if (parameter.getAnnotation(OptionalParam.class) != null) {
                if (parameter.getType().isPrimitive()) {
                    throw new IllegalArgumentException("@OptionalParam不能注解于基本数据类型," + method.toString());
                }
                continue;
            }
            if (parameter.getAnnotation(Flag.class) != null) {
                if (parameter.getType() == boolean.class || parameter.getType() == Boolean.class) {
                    continue;
                }
                throw new IllegalArgumentException("@Flag只能注解与布尔类型," + method.toString());
            }
            Class type;
            if (parameter.isVarArgs() || parameter.getType().isArray()) {
                //可变参数
                type = parameter.getType().getComponentType();
            } else {
                type = parameter.getType();
            }
            ParamParser parser = ParamParsers.getParser(type);
            if (parser == null) {
                throw new IllegalArgumentException("无法解析的参数类型,parameter=" + parameter.toString() + ",method=" + method.toString());
            }
        }
    }

    public String getDesc() {
        return desc;
    }

    void setDesc(String desc) {
        this.desc = desc;
    }

}
